package client;

import java.util.Properties;
import java.util.Scanner;

import monitor.Monitor;
import monitor.MonitorHelper;

import org.omg.CORBA.ORB;
import org.omg.CosNaming.NamingContextExt;
import org.omg.CosNaming.NamingContextExtHelper;
import org.omg.PortableServer.POA;
import org.omg.PortableServer.POAHelper;

import euclid.*;
import euclid.CoordinatorPackage.exInvalidParameter;
import euclid.CoordinatorPackage.exNoStarter;

/**
 * main class for the client
 *
 */
public class Client{
	private static ORB orb;
	private static euclid.Coordinator coordinator;
	private static Monitor monitor;
	
	public static void main(String[] args){
		if(args.length != 4)
		{
			System.err.println("<orbd host> <orbd port> <coordinator name> <monitor name>");
			System.exit(-1);
		}
		try {
			//args[0] = host
			//args[1] = port
			//args[2] = name of the coordinator to bind
			//args[3] = name of the monitor to bind
			Integer.parseInt(args[1]);
			String coordName = args[2];
			String monitorName = args[3];
			Properties props = new Properties();
			props.put("org.omg.CORBA.ORBInitialPort", args[1]);
			props.put("org.omg.CORBA.ORBInitialHost",args[0]);
			orb = ORB.init(args,props);
			System.out.println("ORB initialized.");
			
			//get the reference of rootPOA and activate POA Manager
			POA rootPoa =
					POAHelper.narrow(orb.resolve_initial_references("RootPOA"));
			rootPoa.the_POAManager().activate();
			
			NamingContextExt nc = NamingContextExtHelper.narrow(
					orb.resolve_initial_references("NameService"));
			
			try{
                //get the reference of the coordinator with the name given by the user
                coordinator = CoordinatorHelper.narrow(nc.resolve_str(coordName));
                
                //the class ClientImpl is used for register the client to the coordinator.
                ClientImpl clientImpl = new ClientImpl();
                rootPoa.activate_object(clientImpl);
              //get the object reference of client
    			org.omg.CORBA.Object ref = rootPoa.servant_to_reference(clientImpl);
    			
    			euclid.Client client = ClientHelper.narrow(ref);
    			
                //log the Client
                coordinator.logClient(client);
            } catch(Exception e){
                System.out.println("The coordinator couldn't be found");
                System.exit(-1);
            }
			try{
				//get the reference of the monitor with the name given by the user
				monitor = MonitorHelper.narrow(nc.resolve_str(monitorName));
				coordinator.logMonitor(monitor);
				
			}catch(Exception e){
				System.err.println("No Monitor found");
				monitor=null;
			}
            
            Scanner sc = new Scanner(System.in);
            System.out.println("What do you want to do? Write \"help\" if you need");
            while(true)
            {
            	String text = sc.nextLine();
            	//treat the the text that the client typed in
            	checkText(text);
            }
			
			
		}catch(NumberFormatException e){
			System.err.println("Please check the port");
		}catch(Exception e){
			System.err.println("Problem with the connexion. Please check the parameters.");
			
		}
	}

	/**
	 * Checks the text typed in by the user and treats it
	 * @param text typed in by the user
	 */
	private static void checkText(String text) {
		Scanner sc = new Scanner(System.in);
		if(text.equals("help"))
		{
			System.out.println("List of the possible commands");
			System.out.println("1\tBeginn the calculation of GCD");
			System.out.println("2\tList of the starters");
			System.out.println("3\tEnding the system");
		}
		else
		{
			switch(text.charAt(0)){
				case '1':
					//start the calculation of GCD
					System.out.println("You want to start the calculation");
					System.out.println("Minimum number of gcd Process:");
					int minNumberGcdProcess = sc.nextInt();
					System.out.println("Maximum number of gcd Process");
					int maxNumberGcdProcess = sc.nextInt();
					System.out.println("Minimum delay time (in seconds):");
					int minDelayTime = sc.nextInt();
					System.out.println("Maximum delay time (in seconds):");
					int maxDelayTime = sc.nextInt();
					System.out.println("Timeout:");
					int timeout = sc.nextInt();
					System.out.println("GCD to calculate");
					int gcd = sc.nextInt();
					try{
						//ask the coordinator to start the calculation
						coordinator.startGcdCalculation(minNumberGcdProcess, maxNumberGcdProcess,minDelayTime,maxDelayTime,
								timeout,gcd);
					}catch(exInvalidParameter e){
						System.err.println(e.s);
						System.err.println("Retype \"1\" to restart");
					}catch(exNoStarter e){
						System.err.println(e.s);
					}catch (Exception e){
						e.printStackTrace();
					}
					break;
				case '2' :
					System.out.println("List of the starters:");
					try{
						//ask the coordinator the list of the starters
						Starter[] list = coordinator.getStarterList();
						for(Starter starter: list)
						{
							System.out.println("\t" + starter.getName());
						}
					}catch(Exception e){
						e.getMessage();
					}
					break;
				case '3' :
					System.out.println("Ending the system:");
					coordinator.endSystem();
					break;
				default:
					System.err.println("Unknown command");
					break;
			}
		}
		
	}

}
